﻿using System;
using System.Collections.Generic;
using System.Data.Entity;
using System.Linq;
using System.Text;
using CodeContrib;

namespace CodeContribBlog.Data
{
	public class BlogInitializer : CreateDatabaseIfNotExists<BlogContext>
	{
		private readonly string _rootUrl;

		public BlogInitializer() : this("http://blog.local")
		{
		}

		public BlogInitializer(string rootUrl)
		{
			Guard.NotNullOrEmpty(rootUrl, "rootUrl");

			_rootUrl = rootUrl;
		}

		public void Initialize(BlogContext context)
		{
			Seed(context);
		}

		protected override void Seed(BlogContext context)
		{
			//SeedBlog(context, user, "http://blog.local", null); // Default blog (instead of a landing page).
			//SeedBlog(context, user, "http://test.blog.local", "test"); // Subdomain tenant.
			//SeedBlog(context, user, "http://blog.local/test", "test"); // Url path tenant.

			var randomWord = new RandomWord();

			for (var i = 1; i <= 5; i++)
			{
				var user = new User
					           {
						           EmailAddress = string.Format("user{0}@codecontrib.com", i),
						           Name = string.Format("User {0}", i)
					           };

				user.SetPassword("test1234");

				var tenant = randomWord.Next();

				var uriBuilder = new UriBuilder(_rootUrl);
				uriBuilder.Path = tenant;

				SeedBlog(context, user, uriBuilder.ToString(), tenant);
			}

			base.Seed(context);
		}

		private void SeedBlog(BlogContext context, User user, string url, string slug)
		{
			var randomSentence = new RandomSentence();

			var blog = new Blog
				           {
					           Slug = slug,
					           Subtitle = randomSentence.Next().Replace(".", string.Empty),
					           Title = randomSentence.Next().Replace(".", string.Empty),
					           Url = url,
					           Creator = user
				           };

			context.Blogs.Add(blog);
			context.SaveChanges();

			SeedTags(context, blog, 50);
			SeedPosts(context, blog, user, 100, new RandomDateTime(DateTime.UtcNow.AddYears(-1), DateTime.UtcNow.AddHours(-1)));
			SeedPosts(context, blog, user, 10, new RandomDateTime(DateTime.UtcNow.AddHours(1), DateTime.UtcNow.AddDays(7)));
		}

		private void SeedPosts(BlogContext context, Blog blog, User user, int postCount, RandomDateTime randomDateTime)
		{
			var randomCommentCount = new RandomInteger(0, 11);
			var randomEmailAddress = new RandomEmailAddress();
			var randomFirstName = new RandomFirstName();
			var randomLastName = new RandomLastName();
			var randomParagraph = new RandomParagraph();
			var randomSentence = new RandomSentence();
			var randomTagCount = new RandomInteger(0, 6);
			var randomTagIndex = new RandomInteger(0, context.Tags.Count());
			var randomUrl = new RandomUrl();

			for (var i = 0; i < postCount; i++)
			{
				var createdAt = randomDateTime.Next();
				var publishedAt = new RandomDateTime(createdAt, randomDateTime.MaximumValue).Next();

				var comments = new List<Comment>();

				if (publishedAt <= DateTime.UtcNow)
				{
					for (var j = 0; j < randomCommentCount.Next(); j++)
					{
						var comment = new Comment
							              {
								              Author = string.Format("{0} {1}", randomFirstName.Next(), randomLastName.Next()),
								              CreatedAt = new RandomDateTime(publishedAt, DateTime.UtcNow).Next(),
								              Body = randomParagraph.Next(),
								              EmailAddress = randomEmailAddress.Next(),
								              Url = randomUrl.Next()
							              };

						comments.Add(comment);
					}
				}

				var tags = new List<Tag>();

				for (var j = 0; j < randomTagCount.Next(); j++)
				{
					tags.Add(context.Tags.OrderBy(t => t.Id).Skip(randomTagIndex.Next()).Take(1).Single());
				}

				var post = new Post
					           {
						           Author = user,
						           Blog = blog,
						           Comments = comments,
						           CreatedAt = createdAt,
						           PublishedAt = publishedAt,
						           Tags = tags,
						           Title = randomSentence.Next().Replace(".", string.Empty)
					           };

				var body = new StringBuilder();

				body.AppendFormat("<p>{0}</p>", randomParagraph.Next());
				body.AppendFormat("<pre class=\"prettyprint linenums\">{0}</pre>", @"&lt;div id=""foo""&gt;
  &lt;p class=""bar""&gt;
    Hello World!
  &lt;/p&gt;
&lt;/div&gt;");
				body.AppendFormat("<p>{0}</p>", randomParagraph.Next());
				body.AppendFormat("<div class=\"well\">{0}</div>", randomSentence.Next());
				body.AppendFormat("<p>{0}</p>", randomParagraph.Next());

				var rows = new StringBuilder();

				for (var j = 0; j < 5; j++)
				{
					rows.AppendFormat(@"<tr>
											<td>{0}</td>
											<td>{1}</td>
											<td>{2}</td>
										</tr>", j + 1, randomFirstName.Next(), randomLastName.Next());
				}

				body.AppendFormat(@"<table class=""table table-hover table-striped table-bordered"">
										<thead>
											<tr>
												<th>#</th>
												<th>First Name</th>
												<th>Last Name</th>
											</tr>
										</thead>
										<tbody>
											{0}
										</tbody>
									</table>", rows);

				body.AppendFormat("<p>{0}</p>", randomParagraph.Next());
				body.AppendFormat("<blockquote><p>{0}</p><small>{1}</small></blockquote>", randomSentence.Next(), string.Format("{0} {1}", randomFirstName.Next(), randomLastName.Next()));
				body.AppendFormat("<p>{0}</p>", randomParagraph.Next());

				post.Body = body.ToString();

				context.Posts.Add(post);
				context.SaveChanges();
			}
		}

		private void SeedTags(BlogContext context, Blog blog, int tagCount)
		{
			var randomWord = new RandomWord();

			for (var j = 0; j < tagCount; j++)
			{
				var tag = new Tag
					          {
						          Blog = blog,
						          Name = randomWord.Next()
					          };

				context.Tags.Add(tag);
				context.SaveChanges();
			}
		}
	}
}